@******************************************************************************
@ File start.S
@ Function: boot up code, setting stack, copy BL2 code to CONFIG_SYS_TEXT_BASE
@******************************************************************************  

/* It is for debuging code by led on/off */
#define LED1 0x00000001
#define LED2 (1<<3)
#define LED3 (1<<2)
#define LED4 (1<<4)
.text
.global _start
_start:
	
	/*
	 * set the cpu to SVC32 mode
	 */
	mrs	r0, cpsr
	bic	r0, r0, #0x1f
	orr	r0, r0, #0xd3
	msr	cpsr,r0
	
	/*
	 * Invalidate L1 I/D
	 */
	mov	r0, #0			@ set up for MCR
	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs
	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache
	mcr	p15, 0, r0, c7, c5, 6	@ invalidate BP array
	mcr p15, 0, r0, c7, c10, 4	@ DSB
	mcr p15, 0, r0, c7, c5, 4	@ ISB
	
	/*
	 * disable MMU stuff and caches
	 */
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0, r0, #0x00002000	@ clear bits 13 (--V-)
	bic	r0, r0, #0x00000007	@ clear bits 2:0 (-CAM)
	orr	r0, r0, #0x00000002	@ set bit 1 (--A-) Align
	orr	r0, r0, #0x00000800	@ set bit 11 (Z---) BTB
	bic	r0, r0, #0x00001000	@ clear bit 12 (I) I-cache
	mcr	p15, 0, r0, c1, c0, 0
	
	ldr r0, =LED1                 
	bl 	led_debug                @ turn on LED1
	
	ldr	sp, =0xD0037D80         @ setting stack, so it can call c function						
	
	adr r0, _start  		@ relocate code	
                                  @ _start running address
	ldr r1, =_start           @ _start link address:CONFIG_SYS_TEXT_BASE 	
	cmp r0, r1
	beq run_on_dram           @ If runnig address is linking address, it will run on dram 
	
	bl  uart_init             @ initalization URAT 
	bl  nand_asm_init         @ initalization NandFlash
	bl  mem_init              @ initalization dram
	
//boot up method
#define PRO_ID_BASE			0xE0000000
#define PRO_ID_OFFSET			0x00
#define OMR_OFFSET			0x04

#define BOOT_ONENAND		0x1
#define BOOT_NAND		0x2
#define BOOT_MMCSD		0x3
#define BOOT_NOR		0x4
#define BOOT_SEC_DEV		0x5

#define INF_REG_BASE			0xE010F000
#define INF_REG3_OFFSET			0x0c

	ldr	r0, =PRO_ID_BASE
	ldr	r1, [r0,#OMR_OFFSET]
	bic	r2, r1, #0xffffffc1

	/* NAND BOOT */
	cmp	r2, #0x0		@ 512B 4-cycle
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x2		@ 2KB 5-cycle
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x4		@ 4KB 5-cycle	8-bit ECC
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x6		@ 4KB 5-cycle	16-bit ECC
	moveq	r3, #BOOT_NAND

	cmp	r2, #0x8		@ OneNAND Mux
	moveq	r3, #BOOT_ONENAND

	/* SD/MMC BOOT */
	cmp     r2, #0xc
	moveq   r3, #BOOT_MMCSD	

	/* NOR BOOT */
	cmp     r2, #0x14
	moveq   r3, #BOOT_NOR	

	/* Uart BOOTONG failed */
	cmp     r2, #(0x1<<4)
	moveq   r3, #BOOT_SEC_DEV

	ldr	r0, =INF_REG_BASE
	str	r3, [r0, #INF_REG3_OFFSET]
	
	ldr	r1, [r0, #INF_REG3_OFFSET]
	cmp	r1, #BOOT_NAND		/* 0x0 => boot device is nand */
	beq	nand_boot_210
	cmp     r1, #BOOT_MMCSD
	beq     mmcsd_boot_210
	
nand_boot_210:
	mov r0, #'N'
	bl  putc
	bl  board_init_f_nand     @ copy bl2 code to dram，and skip it copy address.

mmcsd_boot_210:
	mov r0, #'S'
	bl  putc
	bl  board_init_f_mmc

run_on_dram:			 
    	ldr r0, =LED4   	@turn on  led 4
    	bl  led_debug			 
	bl  main                @ skip		

halt:
	b halt


led_debug:     
	ldr     R2,=0xE0200040      	@ Set R2 as GPBCON
                                	@ GPBCON is GPB GPIO function controller register.
                             		@ It can be GPIO as input:1 output 2, and the bits is 4.
	ldr     R1,=0x00001111        
	str     R1,[R2]                 @ Set GPB_0 - GBP3 as output, [15:0]=0x1111
	
	ldr     R2,=0xE0200044      	@ Set R2 as GPBDAT
                              		@ GPBDAT can be read and wirte GPB GPIO data.
	#mov     R0,#0x00000001         @ 
                                        @ 
	str     R0,[R2]                 @ Write R0(as input args) to GPB. 
	mov pc, lr



	/* Setting GPIO for NAND */
	/* This setting is NAND initialze code at booting time in iROM. */
	
nand_asm_init:
	
/*
 * Nand Interface Init for SMDKC110
 */
 
#define ELFIN_GPIO_BASE			0xE0200000 
#define ELFIN_NAND_BASE			0xB0E00000
#define NFCONF_VAL	    (2<<23)|(7<<12)|(7<<8)|(7<<4)|(1<<3)|(0<<2)|(1<<1)|(0<<0)
#define NFCONT_VAL      (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x2<<1)|(1<<0)

//#define  NFCONF_VAL     (0<<25)|(0x3<<23)|(7<<12)|(7<<8)|(7<<4)|(1<<3)|(0<<2)|(1<<1)|(0<<0)
//#define NFCONT_VAL      (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(1<<5)|(0x2<<1)|(1<<0)

#define MP01CON_OFFSET 			0x2E0
#define MP01PUD_OFFSET 			0x2E8
#define MP03CON_OFFSET      0x320
#define MP03PUD_OFFSET      0x328
#define NFCONF_OFFSET       0x00
#define NFCONT_OFFSET       0x04
 

	ldr	r0, =ELFIN_GPIO_BASE

	ldr	r1, [r0, #MP01CON_OFFSET]
	bic	r1, r1, #(0xf<<8)
	orr	r1, r1, #(0x3<<8)
	str	r1, [r0, #MP01CON_OFFSET]

	ldr	r1, [r0, #MP01PUD_OFFSET]
	bic	r1, r1, #(0x3<<4)
	str	r1, [r0, #MP01PUD_OFFSET]

	ldr	r1, [r0, #MP03CON_OFFSET]
	bic	r1, r1, #0xFFFFFF
	ldr	r2, =0x22222222
	orr	r1, r1, r2
	str	r1, [r0, #MP03CON_OFFSET]

	ldr	r1, [r0, #MP03PUD_OFFSET]
	ldr	r2, =0x3fff
	bic	r1, r1, r2
	str	r1, [r0, #MP03PUD_OFFSET]

	ldr	r0, =ELFIN_NAND_BASE

	ldr	r1, [r0, #NFCONF_OFFSET]
	ldr	r2, =0x777F
	bic	r1, r1, r2
	ldr	r2, =NFCONF_VAL
	orr	r1, r1, r2
	str	r1, [r0, #NFCONF_OFFSET]

	ldr	r1, [r0, #NFCONT_OFFSET]
	ldr	r2, =0x707C7
	bic	r1, r1, r2
	ldr	r2, =NFCONT_VAL
	orr	r1, r1, r2
	str	r1, [r0, #NFCONT_OFFSET]

	ldr	r1, [r0, #NFCONF_OFFSET]
	orr	r1, r1, #0x70
	orr	r1, r1, #0x7700
	str     r1, [r0, #NFCONF_OFFSET]

	ldr	r1, [r0, #NFCONT_OFFSET]
	orr	r1, r1, #0x03
	str     r1, [r0, #NFCONT_OFFSET]

	mov	pc, lr
	

